package fem3d;

import inf.text.ArrayFormat;

import java.io.IOException;

import math2.ConstantFunctionRnToR;
import math2.FunctionRnToR;
import fem2.AbstractStructuralStaticDemo;
import fem2.Constraint;
import fem2.Debugger;
import fem2.DistributedLoad;
import fem2.Element;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshGenerator;
import fem2.MeshPart;
import fem2.MeshUtilities;
import fem2.Model;
import fem2.analysis.Analysis;
import fem2.analysis.LinearStaticAnalysis;
import fem2.element.StructuralElement;
import fem2.enu.EchoLevelType;
import fem2.enu.State;
import fem2.enu.StressType;
import fem2.material.StVenantKirchhoffMM;
import fem2.observer.StressObserver;
import fem2.pre_and_post.GidMeshGenerator;
import fem2.pre_and_post.GidPostStructural;

public class SoilBlock extends AbstractStructuralStaticDemo {

	String fn;

	public SoilBlock() {
		projectDir = "/home/hbui/kratos_janosch";
		projectName = "excavation_model.gid";
		meshFileName = "excavation_model_mesh_hex_normal";
		fn = projectDir + '/' + projectName + '/' + meshFileName + ".msh";
	}

	@Override
	public Mesh createMesh() {
		MeshGenerator mg = new GidMeshGenerator(fn);
		Mesh mesh = mg.getMesh(3);
		return mesh;
	}

	@Override
	public Model createConditions(Model m) {
		Mesh mesh = m.getMesh();
		Constraint cx = new Constraint(false, true, true);
		Constraint cy = new Constraint(true, false, true);
		Constraint cz = new Constraint(true, true, false);
		mesh.addConstraint(cz, MeshUtilities.seekNodesOnSurface(mesh, 0, 0, 1, 0));
		mesh.addConstraint(cx, MeshUtilities.seekNodesOnSurface(mesh, 1, 0, 0, 0));
		mesh.addConstraint(cx, MeshUtilities.seekNodesOnSurface(mesh, 1, 0, 0, -6));
		mesh.addConstraint(cy, MeshUtilities.seekNodesOnSurface(mesh, 0, 1, 0, 0));
		mesh.addConstraint(cy, MeshUtilities.seekNodesOnSurface(mesh, 0, 1, 0, -1));

		double g = -11772;
		FunctionRnToR F = new ConstantFunctionRnToR(g);
		for (int i = 0; i < m.countElements(); i++) {
			MeshPart mp = m.getElement(i).getMeshPart();
			DistributedLoad l = new DistributedLoad(mp, null, null, F);
			m.addLoad(l);
		}
		return m;
	}

	@Override
	public MaterialModel createMaterial(Model m) {
		double E = 40e6;
		double nu = 0.3;
		double t = 1.0;
		State ss = State.THREE_DIMENSIONAL;
		return new StVenantKirchhoffMM(E, nu, t, 0, ss);
	}

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm) {
		return new StructuralElement(mp, mm);
	}

	@Override
	public void run() {
		Model m = createModel();
		Mesh mesh = m.getMesh();
		/*
		 * analysis
		 */
		Analysis an = new LinearStaticAnalysis(m);
		// ((NewtonRaphsonBasedStrategy) an.getStrategy())
		// .setMaxNewtonRaphsonIteration(1);
		an.getStrategy().setEchoLevel(EchoLevelType.OUTPUT);
		an.getStrategy().addObserver(new StressObserver(m));
		an.run();

		/*
		 * post process
		 */
		for (int i = 0; i < mesh.countNodes(); i++) {
			System.out.println(ArrayFormat.format(mesh.getNode(i).getUHatLocal()));
		}

		GidPostStructural post = new GidPostStructural(projectDir, projectName, meshFileName);
		post.clearAllPostFiles();
		// post.clearAllPostFiles(meshFileName);
		try {
			post.writeMesh(m, 0);
			post.writeNodalDisplacementResults(m, 0);
			post.writeGaussPointStressResults(m, 0, StressType.CAUCHY_STRESS);
			// post.moveAllPostFiles(meshFileName);
		} catch (IOException e) {
			throw new Error("Write failed: " + e.getMessage());
		}

		Debugger.watch("Analysis completed");
	}

	public static void main(String[] args) {
		AbstractStructuralStaticDemo demo = new SoilBlock();
		demo.run();
	}
}
